import useRcs2AgvStore, { RcsAgvInfoUpdateVo, RcsAgvInfoVo } from 'src/stores/useRcs2AgvStore';
import useLoginInfoStore from 'src/stores/useLoginInfoStore'

export default class Rcs2WebSocket {
  private ws: WebSocket | null = null
  private reconnectAttempts = 0
  private readonly maxReconnectAttempts = 5
  private reconnectTimeout: ReturnType<typeof setTimeout> | null = null
  private rcs2AgvStore: ReturnType<typeof useRcs2AgvStore>
  private loginInfoStore: ReturnType<typeof useLoginInfoStore>
  private fn1: any = null

  constructor() {
    this.loginInfoStore = useLoginInfoStore()
    this.rcs2AgvStore = useRcs2AgvStore()
  }

  public startListener(): void {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      return // 已连接，无需重复连接
    }
    if (!this.loginInfoStore.loginInfo.token ||
      !this.loginInfoStore.loginInfo.rcs2ServerUrl ||
      !this.loginInfoStore.loginInfo.rcs2Password) {
      // 无需连接
      return
    }

    this.connect()
  }

  public stopListener(): void {
    if (!this.ws) {
      return;
    }
    if (this.reconnectTimeout) {
      clearTimeout(this.reconnectTimeout)
      this.reconnectTimeout = null
    }

    if (this.fn1) {
      LCC.off('RefreshAgvList', this.fn1)
      this.fn1 = null
    }

    if (this.ws) {
      this.ws.close()
      this.ws = null
    }
  }

  private connect(): void {
    const token = this.loginInfoStore.loginInfo.token
    if (!token) {
      LCC.msg('WebSocket 连接失败：token 为空', {type: 'error'})
      return
    }

    const host = this.loginInfoStore.loginInfo.rcs2ServerUrl
    if (!host) {
      LCC.msg('WebSocket 连接失败：host 为空', {type: 'error'})
      return
    }


    try {
      const wsUrl = `ws://${host}/websocket`
      this.ws = new WebSocket(wsUrl, token)

      this.ws.onopen = () => {
        console.log('WebSocket 已连接')
        this.reconnectAttempts = 0 // 重置重连次数
        this.sendGetAllVehicles()

        this.fn1 = this.sendGetAllVehicles.bind(this)
        // 监听刷新的全局请求
        LCC.on('RefreshAgvList', this.fn1)
      }

      this.ws.onmessage = (event) => {
        try {
          const message = JSON.parse(event.data)

          switch (message.Action) {
            // case 'ResetUINotification':
            case 'UpdateVehicle':
              this.handleUpdateVehicle(message.Data?.Vehicle)
              break
            case 'UpdateUINotification':
              this.handleUpdateUINotification(message.Data)
              break
            case 'GetAllVehicles':
              this.handleGetAllVehicles(message.Data)
              break
            default:
              console.log('未处理的消息类型:', message.Action, message)
          }
        } catch (error) {
          console.error('WebSocket 消息解析失败:', error)
        }
      }

      this.ws.onclose = () => {
        console.log('WebSocket 已关闭，尝试重连...')
        this.handleReconnect()
      }

      this.ws.onerror = (error) => {
        console.error('WebSocket 错误:', error)
        this.ws?.close()
      }

    } catch (error) {
      console.error('WebSocket 初始化失败:', error)
      this.handleReconnect()
    }
  }

  public sendGetRunmap() {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({Action: 'GetRunMap', Data: '1'}))
    } else {
      console.warn('WebSocket 尚未连接，无法发送 GetRunmap 请求')
    }
  }

  public sendGetAllVehicles(): void {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(JSON.stringify({Action: 'GetAllVehicles', Data: {}}))
    } else {
      console.warn('WebSocket 尚未连接，无法发送 GetAllVehicles 请求')
    }
  }

  private handleGetAllVehicles(data: RcsAgvInfoVo[]): void {
    if (!Array.isArray(data)) return

    // 清空现有列表
    this.rcs2AgvStore.clearList()

    // 插入新数据
    this.rcs2AgvStore.updateAgvList(data)
  }

  private handleUpdateVehicle(data: any): void {
    const vehicle: RcsAgvInfoUpdateVo = data.Vehicle
    if (!vehicle?.Vid) return

    this.rcs2AgvStore.updateRcsAgv(vehicle)
  }

  private handleUpdateUINotification(data: any): void {
    const vid = data.Vid
    const msg = data.Msg

    // 可以调用 system.msg 提示用户
    LCC.msg(`小车 ${vid}：${msg}`, {type: 'warning'})
  }

  private handleReconnect(): void {
    if (this.reconnectAttempts >= this.maxReconnectAttempts) {
      console.warn('WebSocket 重连次数已达上限')
      return
    }

    this.reconnectTimeout = setTimeout(() => {
      this.reconnectAttempts++
      console.log(`第 ${this.reconnectAttempts} 次重连 WebSocket`)
      this.connect()
    }, 3000 * this.reconnectAttempts)
  }
}
